package zb.demo.service.impl;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import zb.blog.base.cache.DataToCache;
import zb.blog.base.util.PropertiesUtil;
import zb.blog.base.util.StringUtil;
import zb.demo.bean.FileUploadBean;
import zb.demo.bean.Result;
import zb.demo.service.IFileInputUploadService;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class FileInputUploadService implements IFileInputUploadService {
    public static final String PATH_LOC_TEM = PropertiesUtil.getPropValue("demo.fileinputupload.path");//临时路径  需要配合tomcat虚拟路径使用
    public static final Long FILE_SZIE_MAX = 10 * 1024 * 1024L;//允许上传的单个文件最大值 (单位：kb)
    public static final Long FILE_SZIE_MIN = 0L;//允许上传的单个文件最大小值 (单位：kb)
    public static final String[] FILE_ARR_SUFFIX = new String[]{"jpg", "png", "gif", "xls", "xlsx", "doc", "docx", "zip", "rar", "txt"};//允许上传的文件后缀类型

    /**
     * @Author: BinZhang
     * @Date: 2018/6/11 17:10
     * @Description:文件上传及保存数据库及其他业务处理等
     */
    @Override
    public Map<String, Object> fileUpload(MultipartFile file, HttpServletRequest request) {
        Result r = this.FileUploadUtil(file, request);
        FileUploadBean b = (FileUploadBean) r.getData();
        //可以从Result对象中获取到FileUploadBean，调用dao进行数据库保存或其他业务错作（略）
        //TODO 保存数据库等操作（略）

        //这里直接将文件信息返回到页面进行展示
        Map<String, Object> map = new HashMap<>();
        if (r.getStatus()) {
            /*获取文件的绝对路径 协议名+"://"+主机地址+":"+端口号+tomcat虚拟路径映射相对地址+文件名
            这里你需要配置一个相对路径叫做source的地址映射到 "D:/IdeaWorkSpace/staticPath/" 文件夹下面。
            通过访问tomcat虚拟地址找到文件实际位置（配置步骤看文档最下方）*/
            String path = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + "/source/" + b.getIp() + "/" + b.getRealPath();
            map.put("path", path);
            map.put("uploadDate", b.getUploadDate());
            map.put("size", String.format("%.2f", b.getSize() / 1024F));
        } else {
            /*这里需要特别注意，你必须返回一个名字是error的key。map返回到页面之后会被转化为json，
            fileinput对象会找到这个json中属性叫error对应的值进行信息提示，并显示在页面上。*/
            map.put("error", r.getMsg());
        }
        return map;
    }


    /**
     * @Author: BinZhang
     * @Date: 2018/6/11 17:02
     * @Description:文件上传时进行校验(可以将其放到util包中)
     */
    public Result FileUploadUtil(MultipartFile file, HttpServletRequest request) {
        Result r = new Result();
        if (file == null) {
            r.setStatus(false);
            r.setMsg("未检测到文件！");
            return r;
        }

        //文件类型校验
        String fileOName = file.getOriginalFilename();
        String suffixName = fileOName.substring(fileOName.lastIndexOf(".") + 1);
        Boolean sufixTem = true;
        for (int i = 0; i < FILE_ARR_SUFFIX.length; i++) {
            if (FILE_ARR_SUFFIX[i].equals(suffixName)) {
                sufixTem = false;
                break;
            }
        }
        if (sufixTem) {
            r.setStatus(false);
            r.setMsg("文件类型必须是以下格式：【" + arrToString(FILE_ARR_SUFFIX) + "】");
            return r;
        }

        //文件大小校验
        Long fileSize = file.getSize();
        if (fileSize > FILE_SZIE_MAX || fileSize <= FILE_SZIE_MIN) {
            r.setStatus(false);
            r.setMsg("文件大小需在" + FILE_SZIE_MIN + "~" + FILE_SZIE_MAX + "KB之间,且不能是0KB");
            return r;
        }
        //ip校验，大于10M的不让上传，没过期的不让上传
        String ip = StringUtil.getIpAddr(request);
        if (!DataToCache.addIpTofileInputUploadMap(ip, fileSize)) {
            r.setStatus(false);
            r.setMsg("小编服务器空间有限，同一个局域网下每天最多只能上传10M大小的文件哦！");
            return r;
        }
        try {
            String fileCurName = System.currentTimeMillis() + "." + suffixName;
            File uploadFile = new File(PATH_LOC_TEM + File.separator + ip);
            if (!uploadFile.exists()) {
                uploadFile.mkdirs();
            }
            file.transferTo(new File(PATH_LOC_TEM + File.separator + ip + File.separator + fileOName));
            //将上传的文件信息记录到bean中，方便保存到数据库或返回到页面
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:SS");
            String uploadDate = sdf.format(new Date());
            FileUploadBean b = new FileUploadBean();
            b.setFileOName(fileOName);
            b.setFileCurName(fileCurName);
            b.setRealPath(fileOName);
            b.setSize(fileSize);
            b.setSuffix(suffixName);
            b.setUploadDate(uploadDate);
            b.setIp(ip);
            b.setBz("文件上传测试！！！");

            //返回成功信息
            r.setStatus(true);
            r.setMsg("文件已经上传！");
            r.setData(b);
            return r;
        } catch (IOException e) {
            //返回错误信息
            e.printStackTrace();
            r.setMsg("文件上传失败！");
            r.setStatus(false);
            return r;
        }
    }

    /**
     * @Author: BinZhang
     * @Date: 2018/6/11 16:54
     * @Description:将数组转化为字符串，元素之间以逗号隔开
     */
    public static String arrToString(String[] arr) {
        String str = "";
        if (arr == null || arr.length <= 0) {
            return str;
        }
        for (int i = 0; i < arr.length; i++) {
            str += arr[i] + "，";
        }
        return str.substring(0, str.length() - 1);
    }

    /**
     * @Author: BinZhang
     * @Date: 2018/6/13 23:20
     * @Description:根据ip获取上传的文件
     */
    @Override
    public List<Map<String, String>> getUploadFile(HttpServletRequest request) {
        List<Map<String, String>> list = new ArrayList<>();
        String ip = StringUtil.getIpAddr(request);
        if (ip == null || ip.trim().length() <= 0) {
            return null;
        }
        String path = PATH_LOC_TEM + File.separator + ip;
        File file = new File(path);
        if (!file.exists()) {
            return null;
        }
        String[] arr = file.list();
        for (int i = 0; i < arr.length; i++) {
            String fullPath = path + File.separator + arr[i];
            File f = new File(fullPath);
            if (f.isFile()) {
                Map<String, String> map = new HashMap<>();
                String fileSize = String.format("%.2f", f.length() / 1024F);//kb
                String fileName = f.getName();
                long lastModified = f.lastModified();
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                Date date = new Date(lastModified);
                String s = /*request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + */"/source/" + ip + "/" + fileName;
                map.put("fileName", fileName);
                map.put("size", fileSize);
                map.put("uploadDate", simpleDateFormat.format(date));
                map.put("path", s);
                list.add(map);
            }
        }
        return list;
    }
}
